home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Extensions / Numerical / Demo / life.py next >
Encoding:
Python Source  |  2000-06-23  |  2.6 KB  |  104 lines

  1.  
  2. """A Python implementation of Conway's Life
  3.  
  4. Michael Wohlgenannt writes this about Life:
  5.   "For a single cell there are two distinct states, dead and alive. A living
  6.   cell dies of boredom if there are less than two living neighbours (all in
  7.   all there are eight). A dead cell gets back to life again if there are
  8.   exactly three living neighbours. The last rule is that a living cell dies
  9.   if there are more than three living neighbours.
  10.   A lot of cell configurations that can be constructed show a peculiar and
  11.   amusing behaviour. Some stay as they are, dead or alive, some oscillate,
  12.   some even propagate."
  13. """
  14.  
  15. # 26 august 1998, Just van Rossum <just@letterror.com>
  16.  
  17. from Numeric import *
  18. import sys
  19. import string
  20.  
  21. def life(cells):
  22.     # convert cells to bytes for speed
  23.     cells = cells.astype(Int8)
  24.  
  25.     # calculate how many neibors each cell has
  26.     neighbors = shift_left(shift_up(cells))
  27.     neighbors = neighbors + shift_up(cells)
  28.     neighbors = neighbors + shift_right(shift_up(cells))
  29.     neighbors = neighbors + shift_left(cells)
  30.     neighbors = neighbors + shift_right(cells)
  31.     neighbors = neighbors + shift_left(shift_down(cells))
  32.     neighbors = neighbors + shift_down(cells)
  33.     neighbors = neighbors + shift_right(shift_down(cells))
  34.  
  35.     # apply the "Life" rules (see module doc string)
  36.     newcells = logical_or(
  37.             logical_and(
  38.                 cells,
  39.                 logical_and(
  40.                     less_equal(2, neighbors),
  41.                     less_equal(neighbors, 3)
  42.                 )
  43.             ),
  44.             equal(neighbors, 3)
  45.         )
  46.  
  47.     # If I understood it correctly, with "rich comparisons"
  48.     # the above could look like this:
  49.     #
  50.     # newcells = cell and (2 <= neighbors <= 3) or neighbors == 3
  51.     #
  52.     # Now, wouldn't that be nice...
  53.  
  54.     return newcells
  55.  
  56.  
  57. def shift_up(cells):
  58.     return concatenate((cells[1:], cells[:1]))
  59.  
  60. def shift_down(cells):
  61.     return concatenate((cells[-1:], cells[:-1]))
  62.  
  63. def shift_left(cells):
  64.     return transpose(shift_up(transpose(cells)))
  65.  
  66. def shift_right(cells):
  67.     return transpose(shift_down(transpose(cells)))
  68.  
  69. def randomcells(width, height, chance = 5):
  70.     from whrandom import randint
  71.     cells = zeros((height, width), Int8)
  72.  
  73.     _range = range
  74.  
  75.     # fill with noise
  76.     for y in _range(height):
  77.         for x in _range(width):
  78.             cells[y][x] = randint(0, chance) == 0
  79.     return cells
  80.  
  81. def printcells(cells):
  82.     x, y = cells.shape
  83.     thing = "+" + y * "-" + "+"
  84.     lines = [thing]
  85.     for i in range(x):
  86.         list = map(lambda x: " O"[x], cells[i])
  87.         lines.append("|"+string.join(list, "")+"|")
  88.     lines.append(thing)
  89.     print string.join(lines, "\n")
  90.  
  91.  
  92. if __name__ == "__main__":
  93.     import time
  94.     width = 20
  95.     height = 10
  96.     cells = randomcells(width, height)
  97.  
  98.     while 1:
  99.         printcells(cells)
  100.         time.sleep(0.1)
  101.         cells = life(cells)
  102.  
  103.  
  104.